#include<cstdlib>
#include<iostream>
#include <memory>
using namespace std;

//The Parent class. The public method doesn't change. If add a new type of class. The base class doesn't need to change. 
//The important and difficult task is identify the mutable class
class Operation {
public:
	Operation():mNumberA(0),mNumberB(0){}
	~Operation(){}
	int get_NumberA()
	{
		return mNumberA;
	}
	void set_NumberA(int iNumberA)
	{
		mNumberA = iNumberA;
	}
	int get_NumberB()
	{
		return mNumberB;
	}
	void set_NumberB(int iNumberB)
	{
		mNumberB = iNumberB;
	}
	virtual int get_Result()
	{
		int result = 0;
		return result;
	}

protected: 
	int mNumberA;
	int mNumberB; 
};
//Add new type don't need add the parent class 
class AddOperation : public Operation
{
public:
	virtual ~AddOperation(){}
	int get_Result()
	{
		return mNumberA + mNumberB;
	}
};



class MinusOperation : public Operation
{
public:
	virtual ~MinusOperation(){}
	int get_Result()
	{
		return mNumberA - mNumberB;
	}
};

class MultipleOperation : public Operation
{
public:
	virtual ~MultipleOperation(){}
	int get_Result()
	{
		return mNumberA * mNumberB;
	}
};

class DivideOperation : public Operation
{
public:
	virtual ~DivideOperation(){}
	int get_Result()
	{
		if(mNumberB == 0 ) throw 0 ;
		return mNumberA + mNumberB;
	}
};

//Factory class. 
//Note here: While Add ,Edit, Remove or Delete the class. This class need change accordinglly. 

class IFactory 
{
public:
	virtual Operation* CreateOperation() = 0;
};

class MinusFactory : public IFactory
{
public:
	Operation* CreateOperation()
	{
		return new MinusOperation();
	}
};

class AddFactory : public IFactory
{
public:
	Operation* CreateOperation()
	{
		return new AddOperation();
	}
};

class MultipleFactory :public IFactory
{
public:
	Operation* CreateOperation()
	{
		return new MultipleOperation();
	}
};

class DivideFactory : public IFactory
{
public:
	Operation* CreateOperation()
	{
		return new DivideOperation();
	}
};

int main()
{
	
	std::cout<<"Please Input Number A, operator  and number B (One example 12 + 13)"<<std::endl;
	int i = 0 , j = 0;
	char opt;
	std::cin >> i >> opt >> j; 

	//use smart pointer to hold the interface. 
	
	shared_ptr<IFactory> lFactory;
	switch(opt)
	{
		case '+':	
			lFactory = make_shared<AddFactory>();
			break;
		case '-':
			lFactory = make_shared<MinusFactory>();
			break;
		case  '*':
			lFactory = make_shared<MultipleFactory>();
			break;
		case  '/':
			lFactory = make_shared<DivideFactory>();
			break;
		default:
			break;
	}
	if (!lFactory.get())
	{
		cout << "Cannot create operation" << endl;
		return -1;
	}

	auto_ptr<Operation> lOperation(lFactory->CreateOperation());
	lOperation->set_NumberA(i);
	lOperation->set_NumberB(j);

	int result = 0;

	try
	{
		result = lOperation->get_Result();
	}
	catch( int i )
	{
		if (i == 0)
		{
			cout<<"Cannot divide 0" << endl;
			return -2;
		}
		else
		{
			cout << "Calculation failure , Please check!"<< endl;
			return -3;
		}

	}
	cout<<"Result:" << result << endl;

	getchar();
	getchar();
	return 0;
}